<?php

/**
 * Main appplication class
 *
 */
class  Application
{
	const CONFIG_FILE           = 'admin_config.xml';
    const CONFIG_SECTION        = 'production';
    const ROUTES_SECTION        = 'routes';
    const CONFIG_DIR            = 'config';
    const MODULES_DIR           = 'admin_modules';
    const PLUGINS_DIR           = 'admin_plugins';
    const CATCH_DIR           	= 'admin_cache';

    protected static $_instance = null;
    protected static $_cache = null;

    private     $_path = ''; 	// string
    private     $_config = NULL;
    private     $_controler = NULL;
    private 	$_router;

    protected function __construct()
    {
    }

    private function _run()
    {

    	$this -> _setupEnvironment()
			  -> _setupAutoloader()
			  -> _loadConfig($this->_path.self::CONFIG_DIR.DIRECTORY_SEPARATOR.self::CONFIG_FILE)
			  -> _setupSession()
			  -> _setupAuth()
			  -> _setupDbConnect()
			  -> _loadRouters()
			  -> _setupLayoutAndView()
			  -> _setupFrontController()
			  -> _registerPlugins()
			  -> _dispatchFrontController();
    }

    public static function run($_root_www_path = '', $config_file = self::CONFIG_FILE)
    {
    	self::getInstance($config_file)->_run();
    }

    public static function getInstance($config_file = self::CONFIG_FILE)
    {
        if (null === self::$_instance) {
            self::$_instance = new self($config_file);
        }
        return self::$_instance;
    }


    /**
	 * Enter description here...
	 *
	 * @return Zend_Cache_Frontend_File
	 */
    public static  function  getCacheInstance(){


        if (null === self::$_cache) {
            $frontendOptions = array(
            'lifetime' => 600, // cache lifetime 10 mins
            'automatic_serialization' => true
            );

            $backendOptions = array(
            'cache_dir' =>  dirname(dirname(__FILE__)).'/cache' // Directory where to put the cache files (make sure to add a trailing slash)
            );

            self::$_cache  =  Zend_Cache::factory('Core', 'File', $frontendOptions, $backendOptions);
        }
        return self::$_cache;
    }

	protected function _setupEnvironment()
	{
		error_reporting( E_ALL | E_NOTICE );
		//error_reporting(E_ALL ^ E_STRICT);
		//error_reporting(0);

		ini_set('display_errors','on');
		ini_set('display_startup_errors','on');
		iconv_set_encoding("internal_encoding", "UTF-8");
		mb_internal_encoding( 'UTF-8' );
		date_default_timezone_set('Europe/Kiev');

		//set_include_path(get_include_path() . PATH_SEPARATOR . realpath( dirname(__FILE__))  . PATH_SEPARATOR . '../'.self::PLUGINS_DIR.'/');
		set_include_path( realpath( dirname(__FILE__))  . PATH_SEPARATOR . '../'.self::PLUGINS_DIR.'/'.PATH_SEPARATOR.get_include_path());

		$this->_path =  dirname(dirname(__FILE__)).'/'; //curent path

		return $this;
	}

	protected function  _setupAutoloader()
	{
        require_once 'Zend/Loader/Autoloader.php';

        $this->_autoloader = Zend_Loader_Autoloader::getInstance();
        //$this->_autoloader->registerNamespace('Apk_');
        $this->_autoloader->setFallbackAutoloader(true);

		return $this;
	}

	protected function _setupSession()
	{
        if ( isset($this->_config->auto_session_start) && $this->_config->auto_session_start ){
            require_once 'Zend/Session.php';
            Zend_Session::start();
        }

        Zend_Session::setOptions(array(
        	'cookie_domain' => Zend_Registry::get('config')->cookie->cookie_domain,
        	'cookie_httponly' => 'on',
        	'cookie_lifetime' => Zend_Registry::get('config')->cookie->cookie_lifetime
        ));

		return $this;
	}

	protected function _setupAuth()
	{
        $auth = Zend_Auth::getInstance();
        $auth->setStorage(new Zend_Auth_Storage_Session('public'));

        Zend_Registry::set('auth', $auth);

		return $this;
	}

	protected function _setupDbConnect()
	{
        try {
            $db = Zend_Db::factory($this->_config->database->type, $this->_config->database->toArray());
            Zend_Db_Table_Abstract::setDefaultAdapter($db);
            Zend_Registry::set( 'db', $db );
		    $db->getConnection();
		    $db->query( 'SET NAMES utf8' );
			$db->getProfiler()->setEnabled($this->_config->database->profiler_enabled);
		} catch ( Zend_Db_Adapter_Exception $e ) {
		    	echo $e->getMessage();
		} catch ( Zend_Exception $e ) {
		    	echo $e->getMessage();
		}

        $frontendOptions_Table = array(
        	'lifetime' => 3600,
        	'automatic_serialization' => true
        );

        $type = @Zend_Registry::get('config')->cache->type;

        switch ($type) {
            case 'Memcached':
                $backendOptions  = array(
                'servers' =>  Zend_Registry::get('config')->cache->servers->toArray()
                );
                break;
            case 'File':
                $backendOptions  = array(
                	'cache_dir' =>  realpath( dirname(dirname(__FILE__))).'/'.self::CATCH_DIR
                );
                break;

            default:
                $backendOptions = null;
                break;
        }

        Zend_Registry::set('catch_dir', realpath( dirname(dirname(__FILE__))).'/'.self::CATCH_DIR);

        //echo realpath( dirname(dirname(__FILE__))).'/'.self::CATCH_DIR; die();

        if (!is_null($backendOptions)){
            $table_cache = Zend_Cache::factory('Core', $type, $frontendOptions_Table, $backendOptions);
            Zend_Db_Table_Abstract::setDefaultMetadataCache($table_cache);
        }

		return $this;
	}

	protected function _loadRouters()
	{
        $this->_router =  new Zend_Controller_Router_Rewrite();

		$this->_router->addRoute('view_default', new Zend_Controller_Router_Route(
            ':controller/:id/*',
                array(
                    'module'     => 'default',
                    'controller' => 'index',
                    'action'     => 'edit'
                ),
                array('id' => '\d+')
            ));

        $this->_router->addRoute('id_default', new Zend_Controller_Router_Route(
            ':controller/:action/:id/*',
                array(
                    'module'     => 'default',
                    'controller' => 'index',
                    'action'     => 'edit'
                ),
                array('id' => '\d+')
            ));

		return $this;
	}

	protected function _setupLayoutAndView()
	{
        $view = new Apk_View_Xslt(); //create template object

        $view->addHelperPath($this->_path.self::MODULES_DIR."/helpers", 'Apk_View_Helper');

        $viewRenderer = new Zend_Controller_Action_Helper_ViewRenderer($view);
        $viewRenderer->setViewBasePathSpec($this->_path.self::MODULES_DIR."/:module/view")
        ->setViewScriptPathSpec(':controller/:action.:suffix')
        ->setViewScriptPathNoControllerSpec(':action.:suffix')
        ->setViewSuffix('xsl');

        Zend_Controller_Action_HelperBroker::addHelper($viewRenderer);

		return $this;
	}

	protected function _setupFrontController()
	{
        Zend_Controller_Front::getInstance()
        	-> throwExceptions(false)
        	-> setBaseUrl($this->_config->base_url)
        	-> setRouter( $this->_router )
        	-> setDefaultModule($this->_config->{'default-module'})
        	-> addModuleDirectory($this->_path.self::MODULES_DIR);

        Zend_Registry::set('main_path', $this->_path);

        if (Zend_Registry::get('config')->is_debug==1) define('DEBUG_TYPE', @$_REQUEST['d']);
        else define('DEBUG_TYPE', null);

		return $this;
	}

	protected function _registerPlugins()
	{
        $error_handler = new Zend_Controller_Plugin_ErrorHandler();
        $error_handler->setErrorHandlerController('error')->setErrorHandlerAction('error');

		Zend_Controller_Front::getInstance()
			-> registerPlugin( new Auth() )
			-> registerPlugin($error_handler);

		return $this;
	}

	protected function _dispatchFrontController()
	{
		try{
			Zend_Controller_Front::getInstance()->dispatch();
		}catch ( Exception $e){
			echo $e->getMessage();
		}

		return $this;
	}

    private function _loadConfig($config, $name = self::CONFIG_SECTION )
    {

    	try{
            switch ( TRUE) {
                case is_string($config):
                    //todo:  try?
                    @$config_temp = new Zend_Config_Xml($config,$name);
                    break;
                case is_array($config):
                    $config_temp = new Zend_Config($config);
                    break;
                case ($config instanceof Zend_Config):
                    $config_temp = $config;

                    break;
            }
            $this->_config = $config_temp;
            Zend_Registry::set('config', $this->_config); // save config in registr

        }catch( Zend_Config_Exception $e) {
            die( $e->getMessage() ); //todo: add default error geadndler
        }

        return $this;
    }
}


